package com.mstar.cameracapturetest;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;

import android.graphics.Bitmap;
import android.graphics.Color;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * 
 */

/**
 * @author amos
 * 
 */
public class CapturePicCallback implements PictureCallback {
	private static final String TAG = CapturePicCallback.class.getSimpleName();

	private static final int M_HANDLER_SHOW_IMAGE = 0;
	private static final boolean DUMP_CAPTUREDATA_TO_FILE = true;
	
	private int mIndex = 0;
	
	private Camera mPicCBCamera = null;
	private Handler mPicCBHandler = null;
	private int mPicMemFormat = -1;
	private int mPicFrameRate = -1;
	private int mWidth = -1;
	private int mHeight = -1;
	private int mTravelingMode = -1;

	public CapturePicCallback(Camera c, Handler h, int memformat, int fps) {
		// TODO Auto-generated constructor stub
		mPicCBCamera = c;
		mPicCBHandler = h;
		mPicMemFormat = memformat;
		mPicFrameRate = fps;
	}

	public void setPicMemFormat(int memformat){
		
		mPicMemFormat = memformat;
	}

	public void setPicFrameRate(int fps){
		mPicFrameRate = fps;
	}
	
	public void setResolution(int w, int h){
		mWidth = w;
		mHeight = h;
	}
	
	public void setTravelingMode(int mod){
		mTravelingMode = mod;
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see android.hardware.Camera.PictureCallback#onPictureTaken(byte[],
	 * android.hardware.Camera)
	 */
	@Override
	public void onPictureTaken(byte[] data, Camera camera) {
		// TODO Auto-generated method stub

		int[] intData = null;
		Bitmap bm = null;
		ByteBuffer srcbuffer = null;
		String rawDataFile = null;
		
		try{
			Log.d(TAG, "onPictureTaken data length = " + data.length);
		}catch(NullPointerException npe){
			Log.w(TAG, "onPictureTaken!, data is null. Nothing will be done.");
			return;
		}
		
		switch(mPicMemFormat){
		case MCamera.Parameters.E_TRAVELING_MEM_FORMAT_ABGR8888:
			//intData = new int[data.length / 4];
			//intData = rgba8888ToArgbData(data, 1920, 1080);
			//Log.d(TAG, "Color Format convertion done! intData length = " + intData.length);
			if(DUMP_CAPTUREDATA_TO_FILE){
				if(0 == mPicFrameRate){
					rawDataFile = "abgr8888_mode" + mTravelingMode + "_" +
							mWidth + "_" + mHeight + "_" + mIndex + ".raw";
				}else{
					rawDataFile = "abgr8888_long" + mIndex + ".raw";
				}
				saveDataToFile(rawDataFile, data, data.length);
			}
			
			bm = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
			//bm = Bitmap.createBitmap(intData, 1920, 1080, Bitmap.Config.ARGB_8888);
			srcbuffer = ByteBuffer.wrap(data);
			bm.copyPixelsFromBuffer(srcbuffer);
			break;
			
		case MCamera.Parameters.E_TRAVELING_MEM_FORMAT_YUV422_YUYV:
			if(DUMP_CAPTUREDATA_TO_FILE){
				rawDataFile = "yuv422_" + mIndex + ".yuv";
				saveDataToFile(rawDataFile, data, data.length);
			}
			
			//intData = new int[data.length / 2];
			intData = yuv422ToArgb(data, mWidth, mHeight);
			Log.d(TAG, "Color Format convertion done! intData length = " + intData.length);
			//bm = Bitmap.createBitmap(1920, 1080, Bitmap.Config.ARGB_8888);
			bm = Bitmap.createBitmap(intData, mWidth, mHeight, Bitmap.Config.ARGB_8888);
			//srcbuffer = ByteBuffer.wrap(data);
			//bm.copyPixelsFromBuffer(srcbuffer);
			break;
			
		case MCamera.Parameters.E_TRAVELING_MEM_FORMAT_YC420:
			//intData = new int[data.length *2 / 3];
			if(DUMP_CAPTUREDATA_TO_FILE){
				rawDataFile = "yuv420_" + mIndex + ".yuv";
				saveDataToFile(rawDataFile, data, data.length);
			}
			break;
			
		default:
			Log.e(TAG, "onPictureTaken. Invalid memory format! Do nothing!");
			return ;
		}
		
		mIndex++;
		
		try{
			Log.d(TAG, "bm byte count  = " + bm.getByteCount());
		}catch(NullPointerException npe){
			Log.w(TAG, "onPictureTaken!, data is null. Nothing will be done.");
			return;
		}
		
		Message msg = Message.obtain();
		msg.what = M_HANDLER_SHOW_IMAGE;
		msg.obj = bm;
		mPicCBHandler.sendMessage(msg);
		Log.i(TAG, "create bitmap success!");
	}
	
	private int[] rgba8888ToArgbData(byte[] srcdata, int width, int height){
		int numOfPixel = width * height;  
	    int[] argb = new int[numOfPixel];  
		int i = 0;
		int j = 0;
	    
		Log.d(TAG, "rgba8888ToArgbData in.");
		
	    for (int h = 0; h < height; h++) {
			j = (h + 1) * width - 1;
			for (int w = 0; w < width; w++) {
				//rgba8888 raw data to argb data.
				//int argb = (rgba & 0xFF) << 24 | ((rgba >> 8) & 0xFF) << 16 | ((rgba >> 16) & 0xFF) << 8 | ((rgba >> 24) * 0xFF);
				argb[j] = Color.argb(srcdata[i + 3] & 0xFF, srcdata[i + 2] & 0xFF,	srcdata[i + 1] & 0xFF, srcdata[i] & 0xFF);
				i += 4;
				j--;
			}
		}
	
	    return argb;
	}

	private int[] yuv422ToArgb(byte[] srcdata, int width, int height){  
	    int numOfPixel = width * height;  
	    int positionOfU = numOfPixel;  
	    int positionOfV = numOfPixel/2 + numOfPixel;  
	    int[] argb = new int[numOfPixel];  
	    
	    Log.d(TAG, "yuv422ToArgb in.");
	    
	    for(int i=0; i<height; i++){  
	        int startY = i*width;  
	        int stepUV = i*width/2;  
	        int startU = positionOfU + stepUV;  
	        int startV = positionOfV + stepUV;  
	        for(int j = 0; j < width; j++){  
	            int Y = startY + j;  
	            int U = startU + j/2;  
	            int V = startV + j/2;  
	            int index = Y;
	            int R = (int)((srcdata[Y]&0xff) + 1.4075 * ((srcdata[V]&0xff)-128));  
	            int G = (int)((srcdata[Y]&0xff) - 0.3455 * ((srcdata[U]&0xff)-128) - 0.7169*((srcdata[V]&0xff)-128));  
	            int B = (int)((srcdata[Y]&0xff) + 1.779 * ((srcdata[U]&0xff)-128));  

	            argb[index] = Color.argb(0xFF, R & 0xFF,	G & 0xFF, B & 0xFF);
	        }  
	    }  
	    return argb;  
	}  
	
	private void saveDataToFile(String name, byte[] b, int len){
        Log.i(TAG, "saveDataToFile.");

        FileOutputStream out;
        DataOutputStream dos;


//        File sdRoot = Environment.getExternalStorageDirectory();
//        String dir = "/camera/";
//        File mkDir = new File(sdRoot, dir);
//
//        if (!mkDir.exists())
//            mkDir.mkdirs();
        
        //File dataFile = new File(sdRoot, dir + name);
        //File dataFile =  new File("/mnt/usb/sda1/AMOS/central/guava/capturefile/" + name);
        File dataFile =  new File("/data/app/" + name);

        Log.i(TAG, "dataFile is " + dataFile.getAbsolutePath());

        try {
            out = new FileOutputStream(dataFile);
            dos = new DataOutputStream(out);
            dos.write(b);
            dos.close();
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }
}
